using NUnit.Framework;
using Tycho.Parser.Peg;

namespace Tycho.UnitTests.Grammar {
    [TestFixture]
    public class GIVEN_TermAssertionUtilities_WHEN_ShouldBe_used {
        [Test]
        public void AND_non_terminal_with_integers_tested_THEN_test_must_pass_when_correct_term () {
            var term = new CompositeTerm ("name", null);
            term.Add ("a", new IntegerTerm (3, null), false);
            term.Add ("b", new IntegerTerm (4, null), false);

            term.ShouldBe ("name {a: 3, b: 4}");
        }

        [Test]
        public void AND_non_terminal_with_identifiers_tested_THEN_test_must_pass_when_correct_term () {
            var term = new CompositeTerm ("x", null);
            term.Add ("a", new IdentifierTerm ("three", null), false);
            term.Add ("b", new IdentifierTerm ("four", null), false);

            term.ShouldBe ("x {a: three, b: four}");
        }

        [Test]
        public void AND_non_terminal_with_incorrect_name_THEN_must_not_pass_test () {
            var term = new CompositeTerm ("incorrect-name", null);
            term.Add ("a", new IdentifierTerm ("three", null), false);
            term.Add ("b", new IdentifierTerm ("four", null), false);

            Assert.That (() => term.ShouldBe ("name {a: three, b: four}"), Throws.InstanceOf(typeof (AssertionException)));
        }

        [Test]
        public void AND_list_THEN_test_must_pass_for_list_with_correct_values () {
            var term = new ListTerm (null);
            term.Terms.Add (new IdentifierTerm ("one", null));
            term.Terms.Add (new IntegerTerm (2, null));

            term.ShouldBe ("[one, 2]");
        }

        [Test]
        public void AND_list_THEN_test_must_not_pass_for_list_with_incorrect_values () {
            var term = new ListTerm (null);
            term.Terms.Add (new IdentifierTerm ("one", null));
            term.Terms.Add (new IntegerTerm (2, null));

            Assert.That(() => term.ShouldBe ("[one, 3]"), Throws.InstanceOf(typeof (AssertionException)));
        }

        [Test]
        public void AND_identifier_passed_THEN_must_pass_with_correct_identifier () {
            new IdentifierTerm ("x", null).ShouldBe ("x");
        }

        [Test]
        public void AND_identifier_passed_THEN_must_not_pass_with_incorrect_identifier () {
            Assert.That(() => new IdentifierTerm ("x", null).ShouldBe ("y"), Throws.InstanceOf(typeof (AssertionException)));
        }

        [Test]
        public void AND_integer_passed_THEN_must_pass_with_correct_term () {
            new IntegerTerm (9, null).ShouldBe ("9");
        }

        [Test]
        public void AND_integer_passed_THEN_must_not_pass_with_incorrect_term () {
            Assert.That(() => new IntegerTerm (2, null).ShouldBe ("3"), Throws.InstanceOf(typeof (AssertionException)));
        }
    }
}